
/*
* @version: 1.0
* @Author: zhangq
* @Date: 2022-4-15 
* @LastEditors: zhanggq
* @LastEditTime: 2022-04-15
* @Description: DL/T645协议采集任务实现
*/
#ifndef __DLT645_MESSAGE_MANAGER_H__
#define __DLT645_MESSAGE_MANAGER_H__
#include <stdint.h>
#include <iostream>
#include <memory>

#include "dlt645def.h"
#include "../../common/include/IChannel.h"
#include "../../common/include/IModule.h"

#include "../../../include/global_data_struct.h"
#include "../../../include/protocol_engine_config.h"
#include "../../common/include/CThreadPool.h"
#include "../../common/include/CConfigManager.h"
#include "../../serialProxy/include/SerialProxy.h"
#include "../../common/include/CMosquittoManager.h"
#include <mutex>
using namespace std;

#define  TEMP_STR_LEN           512
#define  DLT645_FRMDATA_LEN     300

class CDlt645MessageManager
{
public:
    CDlt645MessageManager();
    ~CDlt645MessageManager();

    static CDlt645MessageManager &getInstance();

    int  run(std::shared_ptr<CConfigManager> pcm, 
             IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> pmm, 
             IModule &im,
             TASK_PARAMS *pdev_task);
    int  packet_parent_frame(std::shared_ptr<CConfigManager> cm, 
                              std::shared_ptr<TERMINAL_DEVICE> pdev, 
                              uint8_t *data, int &len);

    int  get_embeded_modbusdata(uint8_t* rsp, int rsplen,  uint8_t* modbus_rsp, int& modbuslen);

protected:
    int  run_collect(std::shared_ptr<CConfigManager> pcm,
            IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> pmm,
            TASK_PARAMS *pdev_task);

    int  run_ctrl_cmd(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr, TASK_PARAMS *pdev_task);

    int  run_dlt645_ctrl_cmd(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr, int64_t task_item_id, std::shared_ptr<TERMINAL_DEVICE> dev, TASK_PARAMS *pdev_task);



    int  run_req_taskitem(std::shared_ptr<CConfigManager> pcm,
                            IChannel *channel_ptr,
                            std::shared_ptr<TERMINAL_DEVICE> dev,
                            int64_t task_id,
                            int64_t task_item_id,
                            std::shared_ptr<ST_DL645_RSPDATA> rsp_data);

    int  run_req_get_subseqdata(std::list<std::shared_ptr<ST_DL645_RSPDATA>> &lst_rspdata,int64_t dev_id,
                                const std::string& di, int64_t rule_id, std::shared_ptr<CConfigManager> pcm,
                                IChannel *channel_ptr, std::shared_ptr<TERMINAL_DEVICE> dev, int64_t task_id);

    int  run_read_cmd(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> pmm, TASK_PARAMS *pdev_task);

    int  read_dlt645cmd_hangler(std::shared_ptr<CConfigManager> pcm,
                                 std::shared_ptr<CMosquittoManager> pmm,
                                 std::shared_ptr<TERMINAL_DEVICE> dev,
                                 IChannel *channel_ptr,
                                 int64_t task_item_id,
                                 TASK_PARAMS *pdev_task,
                                 std::list<std::shared_ptr<ST_DL645_RSPDATA>>& lst_rspdata);
    //------------------------------------------------------------------------------------------------------------
    int  run_frozen_collect(std::shared_ptr<CConfigManager> pcm,
                            IChannel *channel_ptr,
                            std::shared_ptr<CMosquittoManager> pmm,
                            TASK_PARAMS *pdev_task);

    int run_req_frozenitem(std::shared_ptr<CConfigManager> pcm,
                            IChannel *channel_ptr,
                            std::shared_ptr<CMosquittoManager> pmm,
                            std::shared_ptr<TERMINAL_DEVICE> dev,
                            int rule_id, std::unordered_map<int, st_dlt645_frozen_param>   mpfrozen_params
                            );
    int run_req_loadrec_item(std::shared_ptr<CConfigManager> pcm,
                            IChannel *channel_ptr,
                            std::shared_ptr<CMosquittoManager> pmm,
                            std::shared_ptr<TERMINAL_DEVICE> dev,
                            int rule_id, st_dlt645_loadrec_param  stfrozen_loadrec,
                            int item_type = ENUM_FROZEN_TYPE_LOADREC
                            );

    int acq_frozendata_withdi(std::string slave_addr, IChannel *channel_ptr, std::string di,
        std::shared_ptr<st_dlt645_frozen_rspdata> pfrozen_rspdata,
        uint8_t* pucdatetime, int timeout = 5000, uint8_t block_num = 0, int frm_fmt = 1);

    int acq_frozen_subseqqdata(std::string slave_addr, IChannel *channel_ptr, uint8_t* pucdi,
        st_frozen_dataitem& stfrozendataitem, int timeout=5000);

    //-----------------------------------------------------------------------------------------------------------------
    void slave_addr_tobcd(std::string& slave_addr, uint8_t*  pbcd, int& len);

private:
    void save_interaction_log(int64_t dev_id, int64_t task_id, uint8_t *req, int req_len, uint8_t *rsp, int rsp_len);
    int  string_tobcd(const std::string& strdi,uint8_t*  pbcd,int& len);
    char ascii_to_decim(char ch);
    void deci_to_bcd(uint8_t* deci, uint8_t* bcd, int len);

    uint8_t get_ctrlcode(uint8_t* pdata, int len);                           //获取帧控制码，含部分校验
    int     verify_dlt645_frame(uint8_t* pdata, int len);
    int64_t get_req_id();

    std::string     get_final_value(std::shared_ptr<DLT645_COMMAND> dlt645cmd, std::string val);
    int             get_hexwrt_data(std::shared_ptr<DLT645_COMMAND> dlt645cmd, std::string final_val, uint8_t* pdata);

    int     get_frozen_time(uint8_t* pfrozentime,int freeze_interval);
    int     get_frmdata_len(uint8_t* pdata, int len, int& startpos);

    void    OutputInfo(uint8_t* pData, int len,bool bsend=true,int64_t dev_id=0);
private:
    /* data */
    static CDlt645MessageManager m_dlt645mm;
    CThreadPool m_thread_pool;

    TASK_PARAMS *m_pdev_task;
    int64_t     c_req_id;
    std::mutex  c_mutex;

    char       m_szinfo[DLT645_FRMDATA_LEN * 3+1];
    char       m_pstr[TEMP_STR_LEN];
    uint8_t    m_pdata[DLT645_FRMDATA_LEN];
    uint8_t    m_prspdata[DLT645_FRMDATA_LEN];
    IModule    c_im;

};


#endif